#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>

// void handler(int signo)// 父进程收到子进程的 17号 信号
// {
//     std::cout << "get a sig: " << signo << " , I am : " << getpid() << std::endl;
//     while (true)// 循环式回收子进程
//     {
//         //pid_t rid = ::waitpid(-1, nullptr, 0);
//         pid_t rid = ::waitpid(-1, nullptr, WNOHANG);// 非阻塞方式去等待子进程
//         // -1:等待任意子进程
//         // nullptr: 不关心子进程的终止状态
//         // 0: 阻塞等待，直到有子进程终止

//         if (rid > 0)
//         {
//             std::cout << "子进程退出了, 回收成功, child id: " << rid << std::endl;
//         }
//         else if(rid == 0)// 当前父进程 没有子进程退出
//         {
//             std::cout << "退出的子进程已经被全部回收了" << std::endl;
//             break;
//         }
//         else if(rid < 0)// 当前进程已经没有子进程了, 等待失败！
//         {
//             std::cout << "wait error!" << std::endl;
//             break;
//         }
//     }
// }

// 1. 验证子进程退出，给父进程发送SIGCHLD
// 2. 我们可不可以基于信号进行子进程回收呢？
int main()
{
    // signal(SIGCHLD, handler);

    // Linux下，将 SIGCHLD的处理动作置为SIG_IGN,这样fork出来的⼦进程在终⽌时会⾃动清理掉
    ::signal(SIGCHLD, SIG_IGN);
    // 问题1：若有 10 个子进程同时退出呢？
    // 每一个信号都能回收吗？

    // 问题2：10个子进程，6个退出了！会出现什么问题？
    // 会一直 waitpid() , 就会出现阻塞！一旦阻塞，
    // 当前代码 就不能返回，父进程就会受到影响，
    // 所以 使用非阻塞方式去等待子进程
    for (int i = 0; i < 10; i++)// 创建多个子进程
    {
        if (fork() == 0) // 子进程
        {
            sleep(5);
            std::cout << "子进程退出" << std::endl;
            exit(0);
        }
    }

    // 父进程 一直不退出
    while (true)
    {
        sleep(1);
    }

    return 0;
}

// volatile int flag = 0;
// void handler(int signo)
// {
//     printf("chang flag 0 to 1\n");
//     flag = 1;
// }

// int main()
// {
//     signal(2, handler);
//     while(!flag);
//     printf("process quit normal\n");

//     return 0;
// }